//============================================================================
// Name        : GA.cpp
// Author      : Andrey Bicalho Santos e Clayson Sandro Celes
// Version     :
// Copyright   : Your copyright notice
// Description : Genetic Algorithm in C++, Ansi-style
//============================================================================

#include <cstdlib>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <cstring>
#include "GA.h"
#include "ensemble_classifiers.h"

using namespace std;

int *Ensemble_classifiers_problem(int number_genes,int number_individuals,int number_ages,int m_rateX,int m_rateY,int k_tournament,int k_elitism,int max_min_type,int criterio_convergencia, const string file_c1,  const string file_c2,  const string file_c3);

//-------------------------------------------------------------------------------------
int main(int argc, char** argv) {

	//load_file(argv[1]); ok


    int number_genes,number_individuals,number_ages,m_rateX,m_rateY,
	    k_tournament,k_elitism,max_min_type,criterio_convergencia;

	string path_file_c1, path_file_c2, path_file_c3;

	if(argc < 2){
		cout << "Insira arquivo Classificador 1: (ex: nome_do_arquivo.txt)" << endl; cin >> path_file_c1;
		cout << "Insira arquivo Classificador 2: (ex: nome_do_arquivo.txt)" << endl; cin >> path_file_c2;
		cout << "Insira arquivo Classificador 3: (ex: nome_do_arquivo.txt)" << endl; cin >> path_file_c3;
		cout << "\nInsira o numero de genes: " << endl; cin >> number_genes;
		cout << "\nInsira o numero de individuos; " << endl; cin >> number_individuals;
		cout << "\nInsira o numero de geracoes: " << endl; cin >> number_ages;
		cout << "\nInsira parametro 1 da taxa de mutacao: " << endl; cin >> m_rateX;
		cout << "\nInsira parametro 2 da taxa de mutacao: " << endl; cin >> m_rateY;
		cout << "\nInsira parametro K do torneio: " << endl; cin >> k_tournament;
		cout << "\nInsira parametro K do elitismo: " << endl; cin >> k_elitism;
		cout << "\nInsira o tipo de problema (1- maximization e 0- minimization): " << endl; cin >> max_min_type;
		cout << "\nInsira o criterio de convergencia: " << endl; cin >> criterio_convergencia;
	}
	else{
		number_genes = atoi(argv[1]);
		number_individuals = atoi(argv[2]);
		number_ages = atoi(argv[3]);
		m_rateX = atoi(argv[4]);
		m_rateY = atoi(argv[5]);
		k_tournament = atoi(argv[6]);
		k_elitism = atoi(argv[7]);
		max_min_type = atoi(argv[8]);
		criterio_convergencia = atoi(argv[9]);
		path_file_c1 = argv[10];
		path_file_c2 = argv[11];
		path_file_c3 = argv[12];
	}


	int *ensemble_classifiers;

	ensemble_classifiers = Ensemble_classifiers_problem(number_genes,number_individuals,number_ages,m_rateX,m_rateY,
			               k_tournament,k_elitism,max_min_type,criterio_convergencia, path_file_c1, path_file_c2, path_file_c3);

	if(ensemble_classifiers) delete[] ensemble_classifiers;

	cout << "\nit works!\n";
	return 0;
}

//-------------------------------------------------------------------------------------
int *Ensemble_classifiers_problem(int number_genes,int number_individuals,int number_ages,int m_rateX,int m_rateY,int k_tournament,int k_elitism,int max_min_type,int criterio_convergencia, const string file_c1,  const string file_c2,  const string file_c3){
		cout << "Cômite de Classificadores\n\n" << endl;

		int *solution_ensemble;

		int index_melhor;

		GA *ensembleProblem;
		ensembleProblem = new GA(number_ages,number_genes,number_individuals,
				                 m_rateX,m_rateY,k_tournament,k_elitism,1);
		Individual *population;
		population = new Individual[number_individuals];
		for(int i=0;i<number_individuals;i++){
			population[i].setNumGenes(number_genes);
			population[i].Initialize();
		}

		int **int_population;

		do{
			//converte o individuo binário para inteiro
			int_population = bin2dec_pop(population,number_individuals);

			//faz cálculo de cmap
			//calcula fitness

			//setFitness to individual
			for(int i=0;i<ensembleProblem->getNumIndividuals();i++)
				//population[i].setFitness(fitness_PrisonerProblem(population,i,number_individuals,solution_map,start,end,dim_solution_map));
			index_melhor = ensembleProblem->getHighestFitnessIndividualIndex(population);
			//mostra melhor indivíduo

			population = ensembleProblem->Run(population);
		}while((ensembleProblem->getCurrentAge() < ensembleProblem->getAge()) );//&& (prisonerProblem->getAverageFitness(population) < (population[prisonerProblem->getHighestFitnessIndividualIndex(population)].getFitness()) - criterio_convergencia));

	return solution_ensemble;
}
//-------------------------------------------------------------------------------------
